knitr::opts_knit$set(root.dir = "/data/home/lyang/Visium_spotlight")
.libPaths(c("/data/home/lyang/R/x86_64-redhat-linux-gnu-library/4.1",
            "/data/home/bioinfo/R/R4.1.0/library_B3.13",
            "/usr/lib64/R/library","/usr/share/R/library") )
dyn.load("/data/home/bioinfo/programs/hdf5-1.12.0/hdf5/lib/libhdf5_hl.so.200")

Load packages

#! /usr/bin/Rscript
# screen -S spotlight_cell2location34
# Rscript run_spotlight.R &>nohup.out&
  
# .libPaths()
# 
# 
# 
# if (!require("BiocManager", quietly = TRUE))
#   install.packages("BiocManager")
# 
# BiocManager::install("SpatialExperiment")




init_require_packages <- function(){
  library(ggplot2)
  library(SPOTlight)
  library(SingleCellExperiment)
  library(SpatialExperiment)
  library(scater)
  library(scran)
  library(Seurat)
  library(SeuratData)
  library(SeuratDisk)
}

init_require_packages()
# spatial_file = "Visium_spatial"
# paste(spatial_file,"rds",sep =".")

Load the spatial data:

if(file.exists("Visium_spatial.rds")){
  rds_file='Visium_spatial.rds'
  spatial <- readRDS(rds_file)
}else{
  data.dir = 'D:/minor_intership_data/Visium_Spatial_Lymph_Node_Data/data'
  
  spatial = Load10X_Spatial( data.dir , filename =
                               "V1_Human_Lymph_Node_filtered_feature_bc_matrix.h5" )
  saveRDS(spatial,"Visium_spatial.rds")
}

Load the single cell data.

# dataset_name = "cell2location" Tabula
dataset_name = "cell2location34"
sc_dataset_file = paste(dataset_name,"sc_dataset.rds",sep ="_")

# library(SeuratDisk)
if(file.exists(sc_dataset_file)){
  rds_file= sc_dataset_file
  sc_dataset <- readRDS(rds_file)
}else{
  import_sc_dataset <- function()
  {
    # Convert("D:/minor_intership_data/TS_Lymph_Node.h5ad", dest = "h5seurat", overwrite = TRUE)
    sc_dataset <- LoadH5Seurat("D:/minor_intership_data/TS_Lymph_Node.h5seurat",assays  = "RNA")
    sc_dataset
    head(sc_dataset@meta.data, 5)
    saveRDS(sc_dataset,'sc_dataset.rds')
    return(sc_dataset)
  }
  sc_dataset = import_sc_dataset()
}  

# colnames(sc_dataset@meta.data) 
# table(sc_dataset@meta.data$CellType2)
# table(sc_dataset@meta.data$Subset)

Quick data exploration:

# annotation = "cell2location34" Tabula
# annotation = "cell2location34"
dataset_name = "cell2location34"
if(dataset_name == "cell2location34"){
  
  cell_type_table = as.data.frame(table(sc_dataset$Subset))
    
}else if(dataset_name == "Tabula"){
  cell_type_table = as.data.frame(table(sc_dataset$cell_ontology_class))
}else if(dataset_name == "cell2location44"){
  cell_type_table = as.data.frame(table(sc_dataset$CellType))
}
  



colnames(cell_type_table) = c("cell_type","frequency")
library(ggplot2)
# Basic barplot
p <- ggplot(data=cell_type_table, aes(x=cell_type, y=frequency,fill=cell_type)) +
  geom_bar(stat="identity")+
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5))+
       geom_text(aes(label=frequency), position=position_dodge(width=0.9), vjust=-0.25)


ggsave(p,filename = "cell_type_histogram.pdf",width = 15,
       height = 20)

print(p)

# Keep cells with clear cell type annotations
# sce <- subset(sce, , !cell_ontology_class %in% c("nan", "CD45"))
# sc_dataset <- subset(sc_dataset, subset = cell_ontology_class != "nan")
sc_reference_markers_file = paste(dataset_name,"sc_reference_markers.rds",sep ="_")
sc_hvg_file = paste(dataset_name,"sc_hvg.rds",sep ="_")

if(file.exists(sc_hvg_file)){
  rds_file= sc_reference_markers_file
  sc_reference_markers <- readRDS(rds_file)
  rds_file= sc_hvg_file
  sc_hvg <- readRDS(rds_file)
}else
  {
  
  qc_filter_sc <- function(sc_dataset,dataset_name){
    if(dataset_name == "Tabula"){
      sc_dataset[['nCount_RNA']] = sc_dataset$n_counts_UMIs
    }else if(dataset_name == "cell2location"){
      sc_dataset[['nCount_RNA']] = sc_dataset$n_counts
    }
    # head(Tabula_sc@meta.data)
    # The [[ operator can add columns to object metadata. This is a great place to stash QC stats
    # Tabula_sc[["percent.mt"]] <- PercentageFeatureSet(Tabula_sc, pattern = "^MT-")
    mt.genes <- grep(pattern = '^MT-', x = rownames(x = sc_dataset@assays$RNA),value = TRUE)
    
    percent.mt <- Matrix::colSums(sc_dataset@assays$RNA[mt.genes, ]) / Matrix::colSums(sc_dataset@assays$RNA)
    
    sc_dataset <- AddMetaData(object = sc_dataset,metadata = percent.mt,
                              col.name = 'percent.mt')
    
    
    # filter cells based on QC metrics
    sc_dataset_filtered <- subset(sc_dataset, subset = n_genes > 200 & n_genes < 5000 & percent.mt < 0.05 )
    return(list("sc"= sc_dataset,"sc_filtered"= sc_dataset_filtered))
    
  }
  
  if(dataset_name=="cell2location" | dataset_name == "cell2location34"){
    a_list = qc_filter_sc(sc_dataset,"cell2location")
  }else if(dataset_name=="Tabula"){
    a_list = qc_filter_sc(sc_dataset,"Tabula")
  }
  
  sc_dataset = a_list$sc
  # Visualize QC metrics as a violin plot
  VlnPlot(sc_dataset, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)
  sc_dataset_filtered = a_list$sc_filtered
  sc_dataset_filtered <- NormalizeData(sc_dataset_filtered, normalization.method = "LogNormalize", scale.factor = 10000)
  head(rownames(sc_dataset_filtered))
  # Get vector indicating which genes are neither ribosomal or mitochondrial
  genes <- !grepl(pattern = "^Rp[l|s]|Mt", x = rownames(sc_dataset_filtered))
  if(dataset_name=="Tabula"){
    Idents(sc_dataset_filtered) <- 'cell_ontology_class'
  }else if(dataset_name=="cell2location"){
    Idents(sc_dataset_filtered) <- 'CellType'
  }else if(dataset_name=="cell2location34"){
    Idents(sc_dataset_filtered) <- 'Subset'
  }
  
  head(Idents(sc_dataset_filtered), 5)
  sc_dataset_filtered <- FindVariableFeatures(sc_dataset_filtered, selection.method = "vst", nfeatures = 3000)
  sc_hvg =VariableFeatures(sc_dataset_filtered)
  saveRDS(sc_hvg,sc_hvg_file)
  sc_reference_markers <- FindAllMarkers(sc_dataset_filtered, min.pct = 0.25,
                                         logfc.threshold = 0.25,max.cells.per.ident=200)
  library(dplyr)
  sc_reference_markers  <- sc_reference_markers %>%
    group_by(cluster) %>%
    slice_max(n = 10, order_by = avg_log2FC)
  saveRDS(sc_reference_markers,sc_reference_markers_file)
  
  
}

Cell Downsampling

sc_dataset.downsampled_file = paste(dataset_name,"sc_dataset.downsampled.rds",sep ="_")

if (file.exists(sc_dataset.downsampled_file)){
  rds_file = sc_dataset.downsampled_file
  sc_dataset_filtered <- readRDS(rds_file)
}else
{
  # downsample to at most 100 per identity
  subsample_cells <- function(sc_dataset,dataset_name)
  {
    
    if(dataset_name == "Tabula"){
      Idents(sc_dataset) <- 'cell_ontology_class'
    }else if(dataset_name == "cell2location"){
      Idents(sc_dataset) <- 'CellType'
    }else if(dataset_name == "cell2location34"){
      Idents(sc_dataset) <- 'Subset'
    }
    table(Idents(sc_dataset))
    unique(Idents(sc_dataset))
    
    
    cell.list <- WhichCells(sc_dataset, idents = unique(Idents(sc_dataset)), 
                            downsample = 1000)
    gc()
    sc_dataset <- sc_dataset[, cell.list]
    # table(sc_dataset$cell_ontology_class)
    saveRDS(sc_dataset,sc_dataset.downsampled_file)
    
    return(sc_dataset)
    
  }
  # subsample fixed numbers of cells from differently sized cell types in a seurat object.
  sc_dataset_filtered = subsample_cells(sc_dataset_filtered,dataset_name)
}

Deconvolution

You are now set to run SPOTlight to deconvolute the spots!

res_file = paste(dataset_name,"res.rds",sep ="_")

if(file.exists(res_file)){
  rds_file = res_file
  res <- readRDS(rds_file)
}else{
  if(dataset_name=="cell2location34"){
    res <- SPOTlight(
      x = sc_dataset_filtered,
      y = spatial@assays$Spatial@counts,
      groups = sc_dataset_filtered$Subset,
      mgs = sc_reference_markers,
      hvg = sc_hvg,
      weight_id = "avg_log2FC",
      group_id = "cluster",
      gene_id = "gene")
    saveRDS(res,res_file)
  }else if(dataset_name=="Tabula")
  {
    res <- SPOTlight(
      x = sc_dataset_filtered,
      y = spatial@assays$Spatial@counts,
      groups = sc_dataset_filtered$cell_ontology_class,
      mgs = sc_reference_markers,
      hvg = sc_hvg,
      weight_id = "avg_log2FC",
      group_id = "cluster",
      gene_id = "gene")
    saveRDS(res,res_file)
  }
  
  
}
# Time for training: 708.35min
# Deconvoluting mixture data

Extract data from SPOTlight:

# Extract deconvolution matrix
head(mat <- res$mat)[, seq_len(6)]
##                    T_CD4+_TfH   DC_CCR7+ T_Treg T_CD4+_naive      T_TfR
## AAACAAGTATCTCCCA-1  0.1712394 0.09197712      0   0.02533235 0.03647274
## AAACAATCTACTAGCA-1  0.0000000 0.00000000      0   0.00000000 0.00000000
## AAACACCAATAACTGC-1  0.1696150 0.03258153      0   0.10231059 0.02398280
## AAACAGAGCGACTCCT-1  0.0000000 0.00000000      0   0.00000000 0.00000000
## AAACAGCTTTCAGAAG-1  0.1644396 0.00000000      0   0.07022688 0.07221897
## AAACAGGGTCTATATT-1  0.0000000 0.00000000      0   0.00000000 0.00000000
##                    T_CD8+_cytotoxic
## AAACAAGTATCTCCCA-1       0.03789942
## AAACAATCTACTAGCA-1       0.00000000
## AAACACCAATAACTGC-1       0.04188913
## AAACAGAGCGACTCCT-1       0.00000000
## AAACAGCTTTCAGAAG-1       0.05083818
## AAACAGGGTCTATATT-1       0.00000000
# Extract NMF model fit
mod <- res$NMF




library(NMF)
## Loading required package: pkgmaker
## Loading required package: registry
## 
## Attaching package: 'pkgmaker'
## The following object is masked from 'package:S4Vectors':
## 
##     new2
## Loading required package: rngtools
## Loading required package: cluster
## NMF - BioConductor layer [OK] | Shared memory capabilities [NO: synchronicity] | Cores 19/20
##   To enable shared memory capabilities, try: install.extras('
## NMF
## ')
## 
## Attaching package: 'NMF'
## The following object is masked from 'package:S4Vectors':
## 
##     nrun
sign <- basis(mod)
colnames(sign) <- paste0("Topic", seq_len(ncol(sign)))
head(sign)
##        Topic1 Topic2 Topic3 Topic4 Topic5 Topic6 Topic7 Topic8 Topic9 Topic10
## IGHG1       0      0      0      0      0      0      0      0      0       0
## IGHG3       0      0      0      0      0      0      0      0      0       0
## IGKC        0      0      0      0      0      0      0      0      0       0
## JCHAIN      0      0      0      0      0      0      0      0      0       0
## LYZ         0      0      0      0      0      0      0      0      0       0
## S100A8      0      0      0      0      0      0      0      0      0       0
##        Topic11 Topic12 Topic13 Topic14 Topic15     Topic16 Topic17 Topic18
## IGHG1        0       0       0       0       0 0.00000e+00       0       0
## IGHG3        0       0       0       0       0 0.00000e+00       0       0
## IGKC         0       0       0       0       0 7.62454e-05       0       0
## JCHAIN       0       0       0       0       0 0.00000e+00       0       0
## LYZ          0       0       0       0       0 0.00000e+00       0       0
## S100A8       0       0       0       0       0 0.00000e+00       0       0
##             Topic19     Topic20     Topic21     Topic22 Topic23       Topic24
## IGHG1  0.0000000000 0.003303984 0.000000000 0.000000000       0  0.000000e+00
## IGHG3  0.0000000000 0.002141480 0.000000000 0.000000000       0  0.000000e+00
## IGKC   0.0000000000 0.002570801 0.000000000 0.000000000       0 9.881313e-324
## JCHAIN 0.0001160582 0.004192363 0.000000000 0.000000000       0  0.000000e+00
## LYZ    0.0000000000 0.000000000 0.002273634 0.003591960       0  0.000000e+00
## S100A8 0.0000000000 0.000000000 0.000000000 0.002751437       0  0.000000e+00
##              Topic25 Topic26 Topic27 Topic28 Topic29 Topic30       Topic31
## IGHG1   0.000000e+00       0       0       0       0       0  0.000000e+00
## IGHG3   0.000000e+00       0       0       0       0       0  0.000000e+00
## IGKC    0.000000e+00       0       0       0       0       0  0.000000e+00
## JCHAIN  0.000000e+00       0       0       0       0       0 4.940656e-324
## LYZ    2.390113e-219       0       0       0       0       0  0.000000e+00
## S100A8  0.000000e+00       0       0       0       0       0  0.000000e+00
##        Topic32      Topic33 Topic34
## IGHG1        0 0.0000000000       0
## IGHG3        0 0.0000000000       0
## IGKC         0 0.0000000000       0
## JCHAIN       0 0.0000000000       0
## LYZ          0 0.0000000000       0
## S100A8       0 0.0004787023       0

Visualization

In the next section we show how to visualize the data and interpret SPOTlight’s results.

Topic profiles

We first take a look at the Topic profiles. By setting facet = FALSE we want to evaluate how specific each topic signature is for each cell identity. Ideally each cell identity will have a unique topic profile associated to it as seen below.

if(dataset_name == "Tabula"){
  plotTopicProfiles(
    x = mod,
    y = sc_dataset_filtered$cell_ontology_class,
    facet = FALSE,
    min_prop = 0.01,
    ncol = 1) +
    theme(aspect.ratio = 1,axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5))
  
  
}else if(dataset_name == "cell2location"){
  plotTopicProfiles(
    x = mod,
    y = sc_dataset_filtered$CellType,
    facet = FALSE,
    min_prop = 0.01,
    ncol = 1) +
    theme(aspect.ratio = 1,axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5))
}else if(dataset_name == "cell2location34"){
  plotTopicProfiles(
    x = mod,
    y = sc_dataset_filtered$Subset,
    facet = FALSE,
    min_prop = 0.01,
    ncol = 1) +
    theme(aspect.ratio = 1,axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5))
  
}

Next we also want to ensure that all the cells from the same cell identity share a similar topic profile since this will mean that SPOTlight has learned a consistent signature for all the cells from the same cell identity.

if(dataset_name == "Tabula"){
  cell_type = sc_dataset_filtered$cell_ontology_class
}else if(dataset_name == "cell2location"){
  cell_type = sc_dataset_filtered$CellType
}else if(dataset_name == "cell2location34"){
  cell_type = sc_dataset_filtered$Subset
}

plotTopicProfiles(
  x = mod,
  y = cell_type,
  facet = TRUE,
  min_prop = 0.01,
  ncol = 5)

plotTopicProfiles(
    x = mod,
    y = cell_type,
    facet = FALSE,
    min_prop = 0.01,
    ncol = 1) +
    theme(aspect.ratio = 1,axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5))

Lastly we can take a look at which genes the model learned for each topic. Higher values indicate that the gene is more relevant for that topic. In the below table we can see how the top genes for Topic1 are characteristic for B cells (i.e. Cd79a, Cd79b, Ms4a1…).

library(NMF)
sign <- basis(mod)
colnames(sign) <- paste0("Topic", seq_len(ncol(sign)))
head(sign)
# This can be dynamically visualized with DT as shown below
# DT::datatable(sign, fillContainer = TRUE, filter = "top")

Spatial Correlation Matrix

See here for additional graphical parameters.

# plotCorrelationMatrix(mat)

Co-localization

Now that we know which cell types are found within each spot we can make a graph representing spatial interactions where cell types will have stronger edges between them the more often we find them within the same spot.

See here for additional graphical parameters.

# plotInteractions(mat, "heatmap")
# plotInteractions(mat, "network")
DimPlot(sc_dataset_filtered, group.by = "Subset", label = TRUE)

# DimPlot(sc_dataset, group.by = "cell_ontology_class")
# PCAPlot(sc_dataset, group.by = "cell_ontology_class")
# UMAPPlot(sc_dataset, group.by = "cell_ontology_class")

Scatterpie

We can also visualize the cell type proportions as sections of a pie chart for each spot. You can modify the colors as you would a standard .

# This can be dynamically visualized with DT as shown below
ct <- colnames(mat)
mat[mat < 0.1] <- 0


library(RColorBrewer)

if(dataset_name == "Tabula"){
  n <- 29
}else if(dataset_name == "cell2location"){
  n <- 44
}else if(dataset_name == "cell2location34"){
  n <- 34
}

  
colrs <- brewer.pal.info[brewer.pal.info$colorblind == TRUE, ]
col_vec = unlist(mapply(brewer.pal, colrs$maxcolors, rownames(colrs)))
set.seed(123)
col <- sample(col_vec, n)




# Define color palette
# (here we use 'paletteMartin' from the 'colorBlindness' package)
paletteMartin <- col

pal <- colorRampPalette(paletteMartin)(length(ct))
names(pal) <- ct

plotSpatialScatterpie(
  x = spatial,
  y = mat,
  cell_types = colnames(y),
  img = FALSE,
  scatterpie_alpha = 1,
  pie_scale = 0.4) +
  scale_fill_manual(
    values = pal,
    breaks = names(pal))

Residuals

Lastly we can also take a look at how well the model predicted the proportions for each spot. We do this by looking at the residuals of the sum of squares for each spot which indicates the amount of biological signal not explained by the model.

# spatial_dir = 'D:/minor_intership_data/Visium_Spatial_Lymph_Node_Data/data'
# spatial <- read10xVisium(spatial_dir,
#                          type = "HDF5", data = "raw",
#                         images = "lowres",load = FALSE)
# saveRDS(spatial,"spatial_residual.rds")

# rds_file = "spatial_residual.rds"
# spatial_residual <- readRDS(rds_file)
# 
# spatial_residual$res_ss <- res[[2]][colnames(spatial_residual)]
# xy <- spatialCoords(spatial_residual)
# spatial_residual$x <- xy[, 1]
# spatial_residual$y <- xy[, 2]
# detach("package:SeuratObject", unload=TRUE)
# 
# ggcells(spatial_residual, aes(x, y, color = res_ss)) +
# geom_point() +
#   scale_color_viridis_c() +
# coord_fixed() +
# theme_bw()
rds_file='predictions.assay.rds'
predictions.assay <- readRDS(rds_file)


predictions.assay@data <- t(mat)
meta.features <- as.data.frame(colnames(mat) )
rownames(meta.features) = meta.features[,1]
meta.features$`colnames(mat)` =NULL
predictions.assay@meta.features = meta.features


spatial[["predictions"]] <- predictions.assay

DefaultAssay(spatial) <- "predictions"
table(sc_dataset@meta.data$Subset)
## 
##        B_Cycling          B_GC_DZ          B_GC_LZ       B_GC_prePB 
##             4765             2500             3298               74 
##            B_IFN      B_activated            B_mem          B_naive 
##              199             3575            13476             8924 
##         B_plasma          B_preGC         DC_CCR7+          DC_cDC1 
##             1094              404               42              101 
##          DC_cDC2           DC_pDC             Endo              FDC 
##              173              226              622               76 
##              ILC   Macrophages_M1   Macrophages_M2             Mast 
##              617              121              110               18 
##        Monocytes               NK              NKT           T_CD4+ 
##              306             1372              896             3059 
##       T_CD4+_TfH    T_CD4+_TfH_GC     T_CD4+_naive    T_CD8+_CD161+ 
##             4690             3653             6012             2294 
## T_CD8+_cytotoxic     T_CD8+_naive          T_TIM3+            T_TfR 
##             3890             2253              357             1065 
##           T_Treg             VSMC 
##             2958               40
if(dataset_name == "Tabula"){
  
# p = SpatialFeaturePlot(spatial, features = c("stromal cell", "t cell"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)
# print(p)
# p = SpatialFeaturePlot(spatial, features = c("naive b cell", "b cell"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)
# print(p)
  
}else if(dataset_name == "cell2location"){
  
#  SpatialFeaturePlot(spatial, features = c("T_Treg", "DC_cDC2"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)
# SpatialFeaturePlot(spatial, features = c("DC_cDC1", "DC_cDC2"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)

}else if(dataset_name == "cell2location34"){
  
detach("package:SpatialExperiment", unload=TRUE) 
  
p = SpatialFeaturePlot(spatial, features = c("T_CD4+", "T_CD8+_CD161+","B_GC_LZ"), pt.size.factor = 1.6, ncol = 3, crop = TRUE)
print(p)


p = SpatialFeaturePlot(spatial, features = c("B_plasma", "DC_cDC1"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)
print(p)
SpatialFeaturePlot(spatial, features = c("VSMC", "B_Cycling"), pt.size.factor = 1.6, ncol = 2, crop = TRUE)
}

# table(sc_dataset@meta.data$Subset)

Session information

sessionInfo()
## R version 4.1.0 (2021-05-18)
## Platform: x86_64-redhat-linux-gnu (64-bit)
## Running under: Red Hat Enterprise Linux
## 
## Matrix products: default
## BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats4    parallel  stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] RColorBrewer_1.1-2          NMF_0.23.0                 
##  [3] cluster_2.1.2               rngtools_1.5.2             
##  [5] pkgmaker_0.32.2             registry_0.5-1             
##  [7] SeuratDisk_0.0.0.9019       stxKidney.SeuratData_0.1.0 
##  [9] ssHippo.SeuratData_3.1.4    SeuratData_0.2.1           
## [11] SeuratObject_4.0.4          Seurat_4.1.0               
## [13] scran_1.20.1                scater_1.20.1              
## [15] scuttle_1.2.1               SingleCellExperiment_1.14.1
## [17] SummarizedExperiment_1.22.0 GenomicRanges_1.44.0       
## [19] GenomeInfoDb_1.28.4         IRanges_2.26.0             
## [21] S4Vectors_0.30.2            MatrixGenerics_1.4.3       
## [23] matrixStats_0.61.0          SPOTlight_0.99.1           
## [25] bigmemory_4.5.36            Biobase_2.52.0             
## [27] BiocGenerics_0.38.0         ggplot2_3.3.5              
## 
## loaded via a namespace (and not attached):
##   [1] utf8_1.2.2                reticulate_1.24          
##   [3] R.utils_2.11.0            tidyselect_1.1.1         
##   [5] htmlwidgets_1.5.4         grid_4.1.0               
##   [7] BiocParallel_1.26.2       Rtsne_0.15               
##   [9] scatterpie_0.1.7          DropletUtils_1.12.3      
##  [11] munsell_0.5.0             ScaledMatrix_1.0.0       
##  [13] codetools_0.2-18          ica_1.0-2                
##  [15] statmod_1.4.36            future_1.23.0            
##  [17] miniUI_0.1.1.1            withr_2.4.3              
##  [19] colorspace_2.0-2          highr_0.9                
##  [21] knitr_1.37                rstudioapi_0.13          
##  [23] ROCR_1.0-11               tensor_1.5               
##  [25] listenv_0.8.0             labeling_0.4.2           
##  [27] GenomeInfoDbData_1.2.6    polyclip_1.10-0          
##  [29] farver_2.1.0              bit64_4.0.5              
##  [31] rhdf5_2.36.0              parallelly_1.30.0        
##  [33] vctrs_0.3.8               generics_0.1.2           
##  [35] xfun_0.29                 R6_2.5.1                 
##  [37] doParallel_1.0.17         ggbeeswarm_0.6.0         
##  [39] rsvd_1.0.5                locfit_1.5-9.4           
##  [41] hdf5r_1.3.5               bitops_1.0-7             
##  [43] rhdf5filters_1.4.0        spatstat.utils_2.3-0     
##  [45] DelayedArray_0.18.0       assertthat_0.2.1         
##  [47] promises_1.2.0.1          scales_1.1.1             
##  [49] beeswarm_0.4.0            gtable_0.3.0             
##  [51] beachmat_2.8.1            globals_0.14.0           
##  [53] goftest_1.2-3             rlang_1.0.1              
##  [55] splines_4.1.0             lazyeval_0.2.2           
##  [57] spatstat.geom_2.3-1       yaml_2.2.2               
##  [59] reshape2_1.4.4            abind_1.4-5              
##  [61] httpuv_1.6.5              tools_4.1.0              
##  [63] gridBase_0.4-7            ellipsis_0.3.2           
##  [65] spatstat.core_2.3-2       jquerylib_0.1.4          
##  [67] ggridges_0.5.3            Rcpp_1.0.8               
##  [69] plyr_1.8.6                sparseMatrixStats_1.4.2  
##  [71] zlibbioc_1.38.0           purrr_0.3.4              
##  [73] RCurl_1.98-1.6            rpart_4.1-15             
##  [75] deldir_1.0-6              pbapply_1.5-0            
##  [77] viridis_0.6.2             cowplot_1.1.1            
##  [79] zoo_1.8-9                 ggrepel_0.9.1            
##  [81] magrittr_2.0.2            data.table_1.14.2        
##  [83] magick_2.7.3              scattermore_0.7          
##  [85] lmtest_0.9-39             RANN_2.6.1               
##  [87] fitdistrplus_1.1-6        patchwork_1.1.1          
##  [89] mime_0.12                 evaluate_0.14            
##  [91] xtable_1.8-4              gridExtra_2.3            
##  [93] compiler_4.1.0            tibble_3.1.6             
##  [95] KernSmooth_2.23-20        crayon_1.4.2             
##  [97] R.oo_1.24.0               htmltools_0.5.2          
##  [99] ggfun_0.0.5               mgcv_1.8-38              
## [101] later_1.3.0               tidyr_1.2.0              
## [103] DBI_1.1.2                 tweenr_1.0.2             
## [105] rappdirs_0.3.3            MASS_7.3-54              
## [107] Matrix_1.4-0              cli_3.1.1                
## [109] R.methodsS3_1.8.1         metapod_1.0.0            
## [111] igraph_1.2.11             pkgconfig_2.0.3          
## [113] bigmemory.sri_0.1.3       plotly_4.10.0            
## [115] spatstat.sparse_2.1-0     foreach_1.5.2            
## [117] vipor_0.4.5               bslib_0.3.1              
## [119] dqrng_0.3.0               XVector_0.32.0           
## [121] stringr_1.4.0             digest_0.6.29            
## [123] sctransform_0.3.3         RcppAnnoy_0.0.19         
## [125] spatstat.data_2.1-2       rmarkdown_2.11           
## [127] leiden_0.3.9              uwot_0.1.11              
## [129] edgeR_3.34.1              DelayedMatrixStats_1.14.3
## [131] shiny_1.7.1               rjson_0.2.21             
## [133] lifecycle_1.0.1           nlme_3.1-152             
## [135] jsonlite_1.7.3            Rhdf5lib_1.14.2          
## [137] BiocNeighbors_1.10.0      viridisLite_0.4.0        
## [139] limma_3.48.3              fansi_1.0.2              
## [141] pillar_1.7.0              lattice_0.20-44          
## [143] fastmap_1.1.0             httr_1.4.2               
## [145] survival_3.2-13           glue_1.6.1               
## [147] png_0.1-7                 iterators_1.0.14         
## [149] bit_4.0.4                 bluster_1.2.1            
## [151] ggforce_0.3.3             stringi_1.7.6            
## [153] sass_0.4.0                HDF5Array_1.20.0         
## [155] nnls_1.4                  BiocSingular_1.8.1       
## [157] dplyr_1.0.8               irlba_2.3.5              
## [159] future.apply_1.8.1